#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include<queue>
#include<utility>
#include<math.h>
#include<string.h>
using namespace std;
#define blue -1
#define red 1
#define vacant 0
const int MAX = 1000000;
#define SEARCH_DEPTH 2
int my_color = blue;
const int SIZE = 11;
const int M = 100;
int new_x = 0, new_y = 0;

struct Chess {
	int min[2] = { MAX,MAX };//最小的邻居节点
	int color = 0;//0是空白点，-1是蓝色，1是红色
	int visited = 0;//表示是否遍历过
	int value = MAX;//存放相应颜色的双距离
};

Chess chess[SIZE][SIZE];

int dx[6] = { 1,-1,1,-1,0,0 };
int dy[6] = { 0,0,-1,1,1,-1 };
//不同的六个方向

int avail_x[SIZE * SIZE], avail_y[SIZE * SIZE]; //合法位置表，当前棋盘最多有size*size个空白位置
int cnt = 0;
bool occupied[SIZE * SIZE];

bool in_board(int x, int y) { return (x >= 0 && x < SIZE && y >= 0 && y < SIZE); }

//可视为当前颜色的可连接点
bool qualify_empty(bool(*unvisited)[SIZE], int x, int y, int color)
{
	if (!in_board(x, y)) return false;
	if (!(unvisited[x][y] == true)) return false;
	if (chess[x][y].color != 0) return false;

	return true;
//	return (in_board(x, y) &&(unvisited[x][y] == true) &&(chess[x][y].color == 0));
}

bool qualify_colored(bool(*unvisited)[SIZE], int x, int y, int color)
{
	return  (in_board(x, y)) && (unvisited[x][y] == true) && (chess[x][y].color == color);
}


//基于一个蓝色点，发现它周围的所有可连接点
void dfs_expand(bool(*unvisited)[SIZE], int startX, int startY, int color)
{
//	if (chess[startX][startY].color == color)
		for (int i = 0; i < 6; i++)
		{
			if (qualify_empty(unvisited, startX + dx[i], startY + dy[i], color))
			{
				unvisited[startX + dx[i]][startY + dy[i]] = false;
			}
			else if (qualify_colored(unvisited,startX+dx[i],startY+dy[i],color))
			{
				unvisited[startX + dx[i]][startY + dy[i]] = false;
				dfs_expand(unvisited, startX + dx[i], startY + dy[i], color);
			}
		}

	return;
}

void dfs_corr(bool(*unvisited_1)[SIZE], bool(*unvisited_2)[SIZE], int startX, int startY, int color)
{
		for (int i = 0; i < 6; i++)
		{
			if (qualify_empty(unvisited_2, startX + dx[i], startY + dy[i], color))
			{
				unvisited_2[startX + dx[i]][startY + dy[i]] = false;
				if ((unvisited_2[startX + dx[i]][startY + dy[i]] == false) && (unvisited_1[startX + dx[i]][startY + dy[i]] == false))
				{
					printf("%d %d", startX + dx[i], startY + dy[i]);
					//cout << "this camed out from checkWin!" << endl;

					exit(0);
				}
			}
			else if (qualify_colored(unvisited_2, startX + dx[i], startY + dy[i], color))
			{
				unvisited_2[startX + dx[i]][startY + dy[i]] = false;

				dfs_corr(unvisited_1,unvisited_2, startX + dx[i], startY + dy[i], color);
			}
		}
	
	return;
}




void checkWin(int color)
{
	bool unvisited_1[SIZE][SIZE];
	bool unvisited_2[SIZE][SIZE];

	memset(unvisited_1, true, sizeof unvisited_1);
	memset(unvisited_2, true, sizeof unvisited_2);


	if (color == red)
	{
		//red upper side

		for (int y = 0; y < SIZE; y++)
		{
			if (qualify_empty(unvisited_1, 0, y, color))
			{
				unvisited_1[0][y] = false;
			}
			else if (qualify_colored(unvisited_1,0,y,color))
			{
				dfs_expand(unvisited_1, 0, y, color);
			}
		}

		//red down side
		for (int y = 0; y < SIZE; y++)
		{
			if (qualify_empty(unvisited_2, SIZE-1, y, color))
			{
				unvisited_2[SIZE-1][y] = false;
				if ((unvisited_2[SIZE-1][y] == false) && (unvisited_1[SIZE-1][y] == false))
				{
					printf("%d %d",SIZE-1, y);
					//cout << "this camed out from checkWin!" << endl;

					exit(0);
				}

			}
			else if (qualify_colored(unvisited_2, SIZE-1, y, color))
			{
				dfs_corr(unvisited_1,unvisited_2, SIZE-1, y, color);
			}
		}
	}
	else
	{
		//blue upper side

		for (int x = 0; x < SIZE; x++)
		{
			if (qualify_empty(unvisited_1, x, 0, color))
			{
				unvisited_1[x][0] = false;
			}
			else if (qualify_colored(unvisited_1, x, 0, color))
			{
				dfs_expand(unvisited_1, x, 0, color);
			}
		}

		//blue down side
		for (int x = 0; x < SIZE; x++)
		{
			if (qualify_empty(unvisited_2, x, SIZE-1, color))
			{
				unvisited_2[x][SIZE-1] = false;
				if (unvisited_2[x][SIZE-1] == false && unvisited_1[x][SIZE-1] == false)
				{
					printf("%d %d", x, SIZE-1);
					//cout << "this camed out from checkWin!" << endl;

					exit(0);
				}

			}
			else if (qualify_colored(unvisited_2, x, SIZE-1, color))
			{
				dfs_corr(unvisited_1, unvisited_2, x, SIZE-1, color);
			}
		}


	}

	return ;
}


void Find(Chess chess[SIZE][SIZE], int x, int y, int now_color) {//通过find改变（x，y）的min数组和value
	if (chess[x][y].color == -now_color) {
		return;
	}

	chess[x][y].visited = 1;
	if (chess[x][y].color == vacant) {
		int now_value = chess[x][y].value;
		for (int i = 0; i < 6; i++) {
			int now_x = x + dx[i];
			int now_y = y + dy[i];

			if (in_board(now_x, now_y)) {
				if (chess[now_x][now_y].color == -now_color) continue;
				int& m0 = chess[now_x][now_y].min[0];
				int& m1 = chess[now_x][now_y].min[1];
				int second = m1;
				if (now_value < m0)
				{
					m1 = m0;
					m0 = now_value;
				}
				else if (now_value < m1) {
					m1 = now_value;
				}
				if (second > m1) {
					if (chess[now_x][now_y].color == vacant)
						chess[now_x][now_y].value = m1 + 1;
					else
						chess[now_x][now_y].value = m1;
					if (chess[now_x][now_y].visited == 1) {
						Find(chess, now_x, now_y, now_color);
					}
				}
			}
		}

	}
	else {//己方点
		int now_m0 = chess[x][y].min[0];
		int now_m1 = chess[x][y].min[1];
		for (int i = 0; i < 6; i++) {
			int now_x = x + dx[i];
			int now_y = y + dy[i];
			if (in_board(now_x, now_y)) {
				if (chess[now_x][now_y].color == -now_color) continue;
				int& m0 = chess[now_x][now_y].min[0];
				int& m1 = chess[now_x][now_y].min[1];
				int second = m1;
				if (now_m1 < m0) {
					m0 = now_m0;
					m1 = now_m1;
				}
				else if (now_m0 < m0) {
					m1 = m0;
					m0 = now_m0;
					if (now_m1 < m1) {
						m1 = now_m1;
					}
				}
				else if (now_m0 < m1) {
					m1 = now_m0;
				}
				if (second > m1) {
					chess[now_x][now_y].value = m1;
					if (chess[now_x][now_y].color == vacant)
						chess[now_x][now_y].value = m1 + 1;
					else
						chess[now_x][now_y].value = m1;
					if (chess[now_x][now_y].visited == 1) {
						Find(chess, now_x, now_y, now_color);
					}
				}
			}
		}
	}
}
// 评估函数e其实算的是利红程度，但是如果你传蓝就会返回负值，就变成利蓝程度，
// 综上,evaluate用于返回一个利This_color程度

int evaluate(int This_color) {
	/*for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			if (board[i][j] == 1) {
				chess[i][j].color = my_color;
			}
			else if (board[i][j] == -1) {
				chess[i][j].color = -my_color;
			}
			else chess[i][j].color = vacant;
		}
	}//构造新棋盘chess*/
	Chess red_up[SIZE][SIZE];
	Chess red_down[SIZE][SIZE];
	Chess blue_left[SIZE][SIZE];
	Chess blue_right[SIZE][SIZE];
	for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			red_up[i][j] = red_down[i][j] = blue_left[i][j] = blue_right[i][j] = chess[i][j];
		}
	}//构造四个辅助棋盘用来计算two-distance
	for (int i = 0; i < SIZE; i++) {//给red_up第一排赋初值
		if (red_up[0][i].color != blue) {
			red_up[0][i].min[0] = red_up[0][i].min[1] = 0;
			if (red_up[0][i].color == vacant) {
				red_up[0][i].value = 1;
			}
			else red_up[0][i].value = 0;
		}
	}
	for (int i = 0; i < SIZE; i++) {//red_down赋初值
		if (red_down[SIZE - 1][i].color != blue) {
			red_down[SIZE - 1][i].min[0] = red_down[SIZE - 1][i].min[1] = 0;
			if (red_down[SIZE - 1][i].color == vacant) red_down[SIZE - 1][i].value = 1;
			else red_down[SIZE - 1][i].value = 0;
		}
	}
	for (int i = 0; i < SIZE; i++) {//blue_left赋初值
		if (blue_left[i][0].color != red) {
			blue_left[i][0].min[0] = blue_left[i][0].min[1] = 0;
			if (blue_left[i][0].color == vacant) blue_left[i][0].value = 1;
			else  blue_left[i][0].value = 0;
		}
	}
	for (int i = 0; i < SIZE; i++) {//blue_right赋初值
		if (blue_right[i][SIZE - 1].color != red) {
			blue_right[i][SIZE - 1].min[0] = blue_right[i][SIZE - 1].min[1] = 0;
			if (blue_right[i][SIZE - 1].color == vacant) blue_right[i][SIZE - 1].value = 1;
			else blue_right[i][SIZE - 1].value = 0;
		}
	}

	//计算red_up
	for (int i = 0; i < SIZE - 1; i++) {
		for (int j = 0; j < SIZE; j++) {
			Find(red_up, i, j, red);
		}
	}
	int m1 = MAX, m0 = MAX;
	for (int i = 0; i < SIZE; i++) {
		int now_value = red_up[SIZE - 1][i].value;
		if (now_value < m0) {
			m1 = m0;
			m0 = now_value;
		}
		else if (now_value < m1) {
			m1 = now_value;
		}
	}
	for (int i = 0; i < SIZE; i++) {
		if (red_up[SIZE - 1][i].color == blue) continue;//计算红距离不考虑蓝色棋子
		else {
			int& now_m0 = red_up[SIZE - 1][i].min[0];
			int& now_m1 = red_up[SIZE - 1][i].min[1];
			int tr = now_m1;
			if (m1 < now_m0) {
				now_m0 = m0;
				now_m1 = m1;
			}
			else if (m0 < now_m0) {
				now_m1 = now_m0;
				now_m0 = m0;
				if (m1 < now_m1) {
					now_m1 = m1;
				}
			}
			else if (m0 < now_m1) {
				now_m1 = m0;
			}
			if (red_up[SIZE - 1][i].color == vacant && now_m1 < MAX)
				red_up[SIZE - 1][i].value = now_m1 + 1;
			else red_up[SIZE - 1][i].value = now_m1;
		}
	}
	//计算red_down的值
	for (int i = SIZE - 1; i >= 0; i--) {
		for (int j = SIZE - 1; j >= 0; j--) {
			Find(red_down, i, j, red);
		}
	}
	m1 = MAX; m0 = MAX;
	for (int i = SIZE - 1; i >= 0; i--) {
		int now_value = red_down[0][i].value;
		if (now_value < m0) {
			m1 = m0;
			m0 = now_value;
		}
		else if (now_value < m1) {
			m1 = now_value;
		}
	}
	for (int i = SIZE - 1; i >= 0; i--) {
		if (red_down[0][i].color == blue) continue;
		else {
			int& now_m0 = red_down[0][i].min[0];
			int& now_m1 = red_down[0][i].min[1];
			int tr = now_m1;
			if (m1 < now_m0) {
				now_m0 = m0;
				now_m1 = m1;
			}
			else if (m0 < now_m0) {
				now_m1 = now_m0;
				now_m0 = m0;
				if (m1 < now_m1) {
					now_m1 = m1;
				}
			}
			else if (m0 < now_m1) {
				now_m1 = m0;
			}
			if (red_down[0][i].color == vacant && now_m1 < MAX)
				red_down[0][i].value = now_m1 + 1;
			else red_down[0][i].value = now_m1;
		}
	}

	//计算blue_left的值
	m1 = m0 = MAX;
	for (int j = 0; j < SIZE; j++) {
		for (int i = 0; i < SIZE; i++) {
			Find(blue_left, i, j, blue);
		}
	}
	for (int i = 0; i < SIZE; i++) {
		int now_value = blue_left[i][SIZE - 1].value;
		if (now_value < m0) {
			m1 = m0;
			m0 = now_value;
		}
		else if (now_value < m1) {
			m1 = now_value;
		}
	}
	for (int i = 0; i < SIZE; i++) {
		if (blue_left[i][SIZE - 1].color == blue) continue;
		else {
			int& now_m0 = blue_left[i][SIZE - 1].min[0];
			int& now_m1 = blue_left[i][SIZE - 1].min[1];
			int tr = now_m1;
			if (m1 < now_m0) {
				now_m0 = m0;
				now_m1 = m1;
			}
			else if (m0 < now_m0) {
				now_m1 = now_m0;
				now_m0 = m0;
				if (m1 < now_m1) {
					now_m1 = m1;
				}
			}
			else if (m0 < now_m1) {
				now_m1 = m0;
			}
			if (blue_left[i][SIZE - 1].color == vacant && now_m1 < MAX)
				blue_left[i][SIZE - 1].value = now_m1 + 1;
			else blue_left[i][SIZE - 1].value = now_m1;
		}
	}

	//计算blue_right的值
	for (int j = SIZE - 1; j >= 0; j--) {
		for (int i = SIZE - 1; i >= 0; i--) {
			Find(blue_right, i, j, blue);
		}
	}
	m1 = MAX; m0 = MAX;
	for (int i = SIZE - 1; i >= 0; i--) {
		int now_value = blue_right[i][0].value;
		if (now_value < m0) {
			m1 = m0;
			m0 = now_value;
		}
		else if (now_value < m1) {
			m1 = now_value;
		}
	}
	for (int i = SIZE - 1; i >= 0; i--) {
		if (blue_right[i][0].color == blue) continue;
		else {
			int& now_m0 = blue_right[i][0].min[0];
			int& now_m1 = blue_right[i][0].min[1];
			int tr = now_m1;
			if (m1 < now_m0) {
				now_m0 = m0;
				now_m1 = m1;
			}
			else if (m0 < now_m0) {
				now_m1 = now_m0;
				now_m0 = m0;
				if (m1 < now_m1) {
					now_m1 = m1;
				}
			}
			else if (m0 < now_m1) {
				now_m1 = m0;
			}
			if (blue_right[i][0].color == vacant && now_m1 < MAX)
				blue_right[i][0].value = now_m1 + 1;
			else blue_right[i][0].value = now_m1;
		}
	}

	priority_queue<int, vector<int>, greater<int>> red_p;
	priority_queue<int, vector<int>, greater<int>> blue_p;
	red_p.push(MAX);
	blue_p.push(MAX);
	for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			red_up[i][j].value += red_down[i][j].value;
			if (red_up[i][j].value >= MAX)//保持max的一致性
				red_up[i][j].value = MAX;
			if (red_up[i][j].color == vacant && red_up[i][j].value <= red_p.top())
				red_p.push(red_up[i][j].value);
			blue_left[i][j].value += blue_right[i][j].value;
			if (blue_left[i][j].value >= MAX)
				blue_left[i][j].value = MAX;
			if (blue_left[i][j].color == vacant && blue_left[i][j].value <= blue_p.top())
				blue_p.push(blue_left[i][j].value);
		}
	}//计算潜力值
	/*cout << endl;
	for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			cout << red_up[i][j].value << " ";
		}
		cout << endl;
	}
	cout << endl;
	for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			cout << blue_left[i][j].value << " ";
		}
		cout << endl;
	}*/
	int pR = red_p.top(), pB = blue_p.top();//最小潜力值
	int aR = 0, aB = 0;//进攻机动性
	/*for (int i = 0; i < SIZE; i++) {
		for (int j = 0; j < SIZE; j++) {
			if (red_up[i][j].color == vacant) {
				if (red_up[i][j].value < pR) {
					aR = 1;
					pR = red_up[i][j].value;
				}
				else if (red_up[i][j].value == pR) {
					aR++;
				}
			}
			if (blue_left[i][j].color == vacant) {
				if (blue_left[i][j].color == vacant) {
					if (blue_left[i][j].value < pB) {
						aB = 1;
						pB = blue_left[i][j].value;
					}
					else if (blue_left[i][j].value == pB) {
						aB++;
					}
				}
			}
		}
	}*///寻找最小潜力值以及进攻机动性
	int e;
	if (This_color == blue && pR == MAX) {
		return -MAX;
	}//当前为蓝色方，而且红色潜力值为无穷，说明
	else if (This_color == red && pB == MAX) {
		return -MAX;
	}
	while (!red_p.empty() && pR == red_p.top()) {
		aR++;
		red_p.pop();
	}
	while (!blue_p.empty() && pB == blue_p.top()) {
		aB++;
		blue_p.pop();
	}
	e = M * (pB - pR) - (aB - aR);//计算估值函数的值
	if (This_color == blue) {
		return e;
	}
	else return -e;
}

int alpha_beta(int alpha, int beta, int depth, int This_color)
{
	int value, best;

	if (depth >= SEARCH_DEPTH)
	{
		return evaluate(-This_color);
	}



	if (cnt == 0) {
		return evaluate(-This_color);
	}

	best = -MAX;


	for (int i = 0; i < cnt; i++) {
		if (occupied[i] == true) continue;
		chess[avail_x[i]][avail_y[i]].color = This_color;
		occupied[i] = true;
		value = -alpha_beta(-beta, -max(alpha, best), depth + 1, -This_color);
		chess[avail_x[i]][avail_y[i]].color = 0;
		occupied[i] = false;

		if (value > best)
		{
			best = value;
			if (depth == 0)
			{
				new_x = avail_x[i];
				new_y = avail_y[i];
			}
		}

		if (best >= beta)
			break;
	}

	return best;
}

//clock_t start, endd;

int main()
{
	int x, y, n;
	//恢复目前的棋盘信息
	scanf("%d", &n);

	for (int i = 0; i < n - 1; i++) {
		scanf("%d%d", &x, &y);

		if (i == 0 && x == -1) { //红方第一条消息永远是（-1，-1），为了保证红方和蓝方都是接受2n-1条消息，并且提示当前为红方
			my_color = red;
		}
		if (x != -1)
			chess[x][y].color = -my_color;	//对方
		scanf("%d%d", &x, &y);

		if (x != -1)
			chess[x][y].color = my_color;	//我方
	}
	scanf("%d%d", &x, &y);


	//  start = clock();
	if (x != -1) chess[x][y].color = -my_color;	//对方 如果x=-1，则说明是红方的第一步棋
	else { printf("1 2\n");	return 0; }

	//此时board[][]里存储的就是当前棋盘的所有棋子信息,x和y存的是对方最近一步下的棋

	if (n > 10)
	{
		checkWin(my_color);
	}

	for (int i = 0; i < SIZE; i++)
		for (int j = 0; j < SIZE; j++)
			if (chess[i][j].color == 0) {
				avail_x[cnt] = i;
				avail_y[cnt] = j;
				cnt++;
			}//寻找当前棋盘的空位置，并对空位置进行计数

	new_x = avail_x[0];
	new_y = avail_y[0];
	
	int e = alpha_beta(-MAX, MAX, 0, my_color);

	printf("%d %d", new_x, new_y);
	
	//cout << "This program ended normally" << endl;
	// endd = clock();
	 //double endtime = (double)(endd - start) / CLOCKS_PER_SEC;*/
	// cout << "Total time:" << endtime * 1000 << "ms" << endl;    //ms为单位
	return 0;
}